#include"HiKernel/HiModuleManager.h"
#include"HiKernel/HiViewer.h"
#include"HiKernel/HiRenderer.h"
#include"HiKernel/HiFramework.h"

#include <string>
#include <windows.h>
#include <Winbase.h>


HiModuleManager *HiModuleManager::Instance()
{
	static HiModuleManager Instance;

	return &Instance;
}

HiModuleManager::HiModuleManager() : HiObject("ModuleManager")
{
	m_vModules.clear();
}

HiModuleManager::~HiModuleManager()
{
	if(m_vModules.empty())
		return;

	for(int i=0; i<m_vModules.size(); i++)
	{
		if(m_vModules[i] != NULL)
		{
			delete m_vModules[i];
			m_vModules[i] = NULL;
		}
	}

	m_vModules.clear();
}

void HiModuleManager::ConfigAll()
{
	for(int i=0; i<m_vModules.size(); i++)
		m_vModules[i]->PreConfig();

	for(int i=0; i<m_vModules.size(); i++)
		m_vModules[i]->PostConfig();
}
/*
void HiModuleManager::ProcessAll()
{
	for(int i=0; i<m_vModules.size(); i++)
		if(m_vModules[i]->GetActive())
			m_vModules[i]->Update();
	HiViewer::GetInstance()->GetRenderer()->BeginScene();
	for(int i=0; i<m_vModules.size(); i++)
		if(m_vModules[i]->GetActive())
			m_vModules[i]->Render();
	HiViewer::GetInstance()->GetRenderer()->EndScene();
}*/

void HiModuleManager::UpdateAll()
{
	for(int i=0; i<m_vModules.size(); i++)
		if(m_vModules[i]->GetActive())
			m_vModules[i]->Update();
}
void HiModuleManager::RenderAll()
{
	for(int i=0; i<m_vModules.size(); i++)
		if(m_vModules[i]->GetActive())
			m_vModules[i]->Render();
}

bool HiModuleManager::HandleMessage(const Telegram& msg)
{
	return false;
}

int HiModuleManager::AddModule(HiModule *pModule)
{
	if(pModule != NULL)
		m_vModules.push_back(pModule);
	else
		return 0;
	return 1;
}

HiModule *HiModuleManager::GetModule(int i)
{
	int num = 0;
	std::vector<HiModule *>::iterator it;
	for(it = m_vModules.begin(); it!=m_vModules.end(); it++)
	{
		num+=1;
		if(num == i)
			return *it;
	}
	return NULL;
}

HiModule *HiModuleManager::FindModule(HiModule *pModule)
{
	int num = 0;
	std::vector<HiModule *>::iterator it;
	for(it = m_vModules.begin(); it!=m_vModules.end(); it++)
	{
		if(*it == pModule)
			return *it;
	}
	return NULL;
}

HiModule *HiModuleManager::FindModule(const std::string &id)
{
	return (HiModule*)HiObject::Find( *((std::vector<HiObject*>*)&m_vModules), id);
}


HiModule* HiModuleManager::FindModule(int id)
{ 
	return (HiModule*)HiObject::Find( *((std::vector<HiObject*>*)&m_vModules), id);
}

int	HiModuleManager::ParseXml(HiXmlNode *xml)
{
	if(xml == NULL)
		return 0;

	std::list<HiXmlNode*> s;
	std::vector<HiXmlNode*> route;

	s.push_back(xml);

	while(!s.empty())
	{
		HiXmlNode* node = s.front();
		s.pop_front();

		if ( node->GetName() == "HiModule" ) 
		{
			SetXmlModule(node);
		} 
		else if ( node->GetName() == "HiRoute" ) 
		{
			route.push_back(node);
		}		
		else 
		{
			for(int i=0;i<node->GetNumChildren();i++)
				s.push_back( node->GetChild(i) );
		}
	}

	for(int i=0; i<route.size(); i++)
		SetXmlRoute( route[i] );

	return 1;
}

int HiModuleManager::SetXmlAttrs(HiXmlNode *xml)
{
	return 0;
}

int HiModuleManager::SetXmlModule(HiXmlNode *xml)
{
	// AddModule
	std::string className = xml->GetAttrs("class");
	std::string dsoName = xml->GetAttrs("dso");


	HiModule* module = HiModule::Load(className, dsoName, xml);

//	module->SetName(className);
	//printf("setXmlModule |%s| |%s|\n", className.c_str(), dsoName.c_str());

	if ( module != NULL )
	{
		std::string name = xml->GetAttrs("id");
		std::string active = xml->GetAttrs("active");
		if(active == "true")
			module->SetActive(true);
		else
			module->SetActive(false);
		module->SetName(name);

		AddModule(module);
		return 1;
	}
	return 0;
}

int HiModuleManager::SetXmlRoute(HiXmlNode *xml)
{
	//HiField *src = m_Modules[3]->GetField("Interpolator");
	//HiField *dst = m_Modules[1]->GetField("caltest");

	//src->Connect(dst);


	std::string sID	  = xml->GetAttrs("id");
	std::string sSorc = xml->GetAttrs("sorc");
	std::string sDest = xml->GetAttrs("dest");


	int d1st, d2st;
	std::string sModule, sElement, sField;


	d1st = sSorc.find(":");
	d2st = sSorc.find(".");

	sModule = sSorc.substr(0,d1st);
	HiModule* moduleSorc= FindModule(sModule);
	
	if ( moduleSorc == NULL ) 
	{
		printf("moduleSorc is NULL\n");
		return 0;
	}

	sField = sSorc.substr(d1st+1,sSorc.size()-d1st-1);
	HiField*  fieldSorc  = moduleSorc->GetField(sField);

	if ( fieldSorc == NULL ) 
	{
		printf("fieldSorc is NULL\n");
		return 0;
	}
	

	d1st = sDest.find(":");
	d2st = sDest.find(".");

	sModule = sDest.substr(0,d1st);
	HiModule* moduleDest = FindModule(sModule);
	
	if ( moduleDest == NULL )
	{
		printf("moduleDest is NULL\n");
		return 0;
	}
	
	sField = sDest.substr(d1st+1,sDest.size()-d1st-1);
	HiField*  fieldDest  = moduleDest->GetField(sField);

	if ( fieldDest == NULL ) 
	{
		printf("fieldDest is NULL\n");
		return 0;
	}

	//fieldSorc->Connect(fieldDest);

	RouteManager->AddRoute(sID, fieldSorc, fieldDest);

/*	if(!AddRoute(fieldSorc, fieldDest))
	{
		std::cout<<"Connect Error"<<std::endl;
	}*/

	float	offset[3], scale[3];
	int		order[3];

	if ( xml->GetAttrs("offset",3, offset ) ) 
		fieldDest->SetOffset(offset);

	if ( xml->GetAttrs("scale",3, scale ) )
		fieldDest->SetScale(scale);

	if ( xml->GetAttrs("order",3, order) )
		fieldDest->SetOrder(order);

	return 0;
}
